package org.aldar.bquest.screens;

import android.R;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.widget.TextView;
import org.aldar.bquest.constants.LandscapeType;
import org.aldar.bquest.entity.*;
import org.aldar.bquest.profile.GameProfile;
import org.aldar.bquest.resources.ResourceManager;
import org.aldar.bquest.sound.GameSound;
import org.aldar.bquest.util.CustomButtonSprite;
import org.aldar.bquest.util.Logger;
import org.aldar.bquest.util.SQLiteHelper;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.Entity;
import org.andengine.entity.IEntity;
import org.andengine.entity.modifier.*;
import org.andengine.entity.scene.IOnSceneTouchListener;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.sprite.Sprite;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.font.Font;
import org.andengine.opengl.font.FontFactory;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.ITiledTextureRegion;
import org.andengine.opengl.texture.region.TextureRegion;
import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.util.math.MathUtils;
import org.andengine.util.modifier.IModifier;

import java.util.*;

import static org.aldar.bquest.constants.LandscapeType.*;
import static org.aldar.bquest.logic.controller.level.LevelDefinition.l;
import static org.aldar.bquest.util.SpriteUtil.revealEntityAndChildren;


public class StartMenuScreen extends LoggedSimpleBaseGameActivity implements IOnSceneTouchListener {

    private static final int CAMERA_WIDTH = 480;
    private static final int CAMERA_HEIGHT = 800;

    private static Logger LOG = new Logger(StartMenuScreen.class);
    private static final int GROUND_Y = 350;
    public static int LANDSCAPE_ITEM_WIDTH = 25;
    private int NUMBER_ITEMS = 0;


    private Entity bgLayer;
    private Entity landscapeLayer;
    private Entity landscapeBaseLayer;
    private Entity heroLayer;
    private Entity logoLayer;
    private Entity popupLayer;

    public static boolean showErrorReport = false;

    private Runnable backButtonAction = null;

    protected Camera mCamera;

    protected Scene scene;
    private SQLiteHelper mSQLiteHelper = new SQLiteHelper(this);

    private BitmapTextureAtlas mFontTexture, bigFontTexture;
    private Font mFont, bigFont;

    private BitmapTextureAtlas heroMovingTexture;
    private TiledTextureRegion heroMovingRegion;

    private BitmapTextureAtlas bgTexture;
    protected TextureRegion bgTextureRegion;
    private BitmapTextureAtlas logoTexture;
    protected TextureRegion logoTextureRegion;

    private BitmapTextureAtlas winTextTexture;
    protected TextureRegion winTextTextureRegion;

    private CustomButtonSprite buttonNewGame;
    private CustomButtonSprite buttonContinueGame;
    private CustomButtonSprite buttonSettings;

    private CustomButtonSprite buttonYesNewGame;
    private CustomButtonSprite buttonNoNewGame;

    private Entity windowConfirmNewGame;
    private HeroSprite heroMovingSprite;
    private BitmapTextureAtlas cloudTexture;
    private TextureRegion cloudTextureRegion;
    private ITiledTextureRegion buttonOkTextureRegion;
    private ITiledTextureRegion buttonYesTextureRegion;
    private ITextureRegion starRegion;


    private List<List<BitmapTextureAtlas>> landScapeTextures;
    protected Map<LandscapeType, List<LsTextureDef>> landScapeTextureRegions;
    Map<LandscapeType, LsTextureDef[]> lsTexturesArr = ResourceManager.getLsTexturesArr();
    private boolean isPopupShown;
    private ITextureRegion settingsPopupBgTextureRegion;
    private CustomButtonSprite buttonOkSettings;
    private Font fontTrebuchetBoldGoldSmall;
    private boolean settingSoundState;
    private boolean settingMusicState;
    private ITextureRegion checkBoxV;
    private ITextureRegion checkBoxN;
    private CustomButtonSprite buttonCloseSettings;
    private ITiledTextureRegion buttonCloseTextureRegion;

    private ITiledTextureRegion buttonContinueRegion;
    private ITiledTextureRegion buttonNewGameRegion;
    private ITiledTextureRegion buttonSettingsRegion;
    private ITextureRegion bgFrameRegion;
    private ITextureRegion loonyRocketCopyright;
    private Entity frameLayer;
    private Runnable closeConfirmAction;
    // ===========================================================
    // Methods for/from SuperClass/Interfaces
    // ===========================================================


    private ITextureRegion load(String filename, int w, int h, Context context) {
        BitmapTextureAtlas texture = new BitmapTextureAtlas(getTextureManager(), w, h, TextureOptions.BILINEAR);
        ITextureRegion region = BitmapTextureAtlasTextureRegionFactory.createFromAsset(texture, context, filename, 0, 0);
        texture.load();
        return region;
    }

    private ITiledTextureRegion loadTiled(String filename, int w, int h, int col, int row, Context context) {
        BitmapTextureAtlas texture = new BitmapTextureAtlas(getTextureManager(), w, h, TextureOptions.BILINEAR);
        ITiledTextureRegion region = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(texture, context, filename, 0, 0, col, row);
        texture.load();
        return region;
    }

    @Override
    public EngineOptions onMyCreateEngineOptions() {
        mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
        EngineOptions opts = new EngineOptions(true, ScreenOrientation.PORTRAIT_FIXED,//TODO replaced "PORTRAIT"
                new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), mCamera);
        opts.getAudioOptions().setNeedsSound(true);
        opts.getAudioOptions().setNeedsMusic(true);
        opts.getRenderOptions().setDithering(true);
        return opts;

    }

    @Override
    protected SQLiteHelper getSqLiteHelper() {
        return mSQLiteHelper;
    }

    @Override
    protected void onMyCreateResources() {
        this.bgTexture = new BitmapTextureAtlas(getTextureManager(), 480, 800, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
        this.bgTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.bgTexture, this, "gfx/startscreen/main_screen_bg.png", 0, 0);
        this.mEngine.getTextureManager().loadTexture(this.bgTexture);

        this.logoTexture = new BitmapTextureAtlas(getTextureManager(), 480, 800, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
        this.logoTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.logoTexture, this, "gfx/startscreen/jewel_road_logo.png", 0, 0);
        this.mEngine.getTextureManager().loadTexture(this.logoTexture);

        this.winTextTexture = new BitmapTextureAtlas(getTextureManager(), 480, 800, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
        this.winTextTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.winTextTexture, this, "gfx/startscreen/popup_newgame_bg.png", 0, 0);
        this.mEngine.getTextureManager().loadTexture(this.winTextTexture);

        heroMovingTexture = new BitmapTextureAtlas(this.getTextureManager(), 1500, 62, TextureOptions.BILINEAR);
        heroMovingRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(heroMovingTexture, this,
                "gfx/go_anim_2.png", 0, 0, 25, 1);
        heroMovingTexture.load();

        cloudTexture = new BitmapTextureAtlas(getTextureManager(), 146, 79, TextureOptions.BILINEAR);
        cloudTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset
                (cloudTexture, this, "gfx/cloud/cloud.png", 0, 0);
        cloudTexture.load();


        settingsPopupBgTextureRegion = load("gfx/startscreen/settings_bg.png", 480, 800, this);
        bgFrameRegion = load("gfx/startscreen/main_screen_frame.png", 480, 800, this);
        buttonOkTextureRegion = loadTiled("gfx/startscreen/btn_ok.png", 310, 65, 2, 1, this);
        checkBoxV = load("gfx/startscreen/checkbox_on.png", 51, 49, this);
        checkBoxN = load("gfx/startscreen/checkbox_off.png", 51, 49, this);
        buttonCloseTextureRegion = loadTiled("gfx/common/btn_x.png", 110, 55, 2, 1, this);
        buttonContinueRegion = loadTiled("gfx/startscreen/btn_mm_continue.png", 630, 65, 2, 1, this);
        buttonNewGameRegion = loadTiled("gfx/startscreen/btn_mm_newgame.png", 630, 65, 2, 1, this);
        buttonSettingsRegion = loadTiled("gfx/startscreen/btn_mm_settings.png", 630, 65, 2, 1, this);
        loonyRocketCopyright = load("gfx/startscreen/2014_c_loony_rocket.png", 256, 58, this);
        buttonYesTextureRegion = loadTiled("gfx/startscreen/btn_yes.png", 310, 65, 2, 1, this);
        starRegion = load("gfx/common/star.png", 8, 8, this);

        this.landScapeTextures = new ArrayList<List<BitmapTextureAtlas>>();
        this.landScapeTextureRegions = new HashMap<LandscapeType, List<LsTextureDef>>();

        BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
        for (LandscapeType lsType : lsTexturesArr.keySet()) {
            LsTextureDef[] textureArr = lsTexturesArr.get(lsType);
            List<LsTextureDef> lsRegions = new ArrayList<LsTextureDef>();
            for (LsTextureDef textureDef : textureArr) {
                if (textureDef.getTextureFilename() != null) {
                    BitmapTextureAtlas texture = new BitmapTextureAtlas(getTextureManager(), textureDef.getWidth(), textureDef.getHeight(), TextureOptions.BILINEAR);
                    textureDef.setTextureAtlas(texture);
                    LOG.i("texture: " + textureDef.getTextureFilename());
                    textureDef.setTextureRegion(BitmapTextureAtlasTextureRegionFactory.createFromAsset(texture, this, "timeline/" + textureDef.getTextureFilename(), 0, 0));
                    getTextureManager().loadTexture(texture);
                }
                BitmapTextureAtlas texture = new BitmapTextureAtlas(getTextureManager(), textureDef.getBaseWidth(), textureDef.getBaseHeight(), TextureOptions.BILINEAR);
                textureDef.setBaseTextureRegion(BitmapTextureAtlasTextureRegionFactory.createFromAsset(texture, this, "timeline/" + textureDef.getBaseTextureFilename(), 0, 0));
                getTextureManager().loadTexture(texture);
                lsRegions.add(textureDef);


            }
            landScapeTextureRegions.put(lsType, lsRegions);
        }

        BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("fonts/");
        this.mFontTexture = new BitmapTextureAtlas(getTextureManager(), 256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
        this.bigFontTexture = new BitmapTextureAtlas(getTextureManager(), 256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
        BitmapTextureAtlas fontTrebuchetTexture2 = new BitmapTextureAtlas(getTextureManager(), 256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
        this.mFont = FontFactory.createFromAsset(getFontManager(), this.mFontTexture, getAssets(), "fonts/Trebuchet_MS.ttf", 14, true, Color.WHITE);
        this.bigFont = FontFactory.createFromAsset(getFontManager(), this.bigFontTexture, getAssets(), "fonts/Trebuchet_MS.ttf", 25, true, Color.BLACK);
        this.fontTrebuchetBoldGoldSmall = FontFactory.createFromAsset(getFontManager(), fontTrebuchetTexture2, getAssets(), "fonts/Trebuchet_MS_bold.ttf", 25, true, android.graphics.Color.YELLOW);
        this.getTextureManager().loadTexture(this.mFontTexture);
        this.getTextureManager().loadTexture(this.bigFontTexture);
        this.getTextureManager().loadTexture(fontTrebuchetTexture2);
        this.getFontManager().loadFont(this.mFont);
        this.getFontManager().loadFont(this.bigFont);
        this.getFontManager().loadFont(this.fontTrebuchetBoldGoldSmall);

    }

    @Override
    protected Scene onMyCreateScene() {

        GameSound sound = new GameSound(this, this.mEngine.getSoundManager(), mEngine.getMusicManager());
        sound.initSound();
        GameSound.setCurrentInstance(sound);
        SQLiteHelper.setCurrentInstance(mSQLiteHelper);
        //场景
        this.scene = new LoggedScene(this);

        bgLayer = new Entity();
        heroLayer = new Entity();
        landscapeLayer = new Entity();
        landscapeBaseLayer = new Entity();
        logoLayer = new Entity();
        popupLayer = new Entity();
        frameLayer = new Entity();
        scene.attachChild(bgLayer);
        scene.attachChild(landscapeLayer);
        scene.attachChild(heroLayer);
        scene.attachChild(landscapeBaseLayer);
        scene.attachChild(frameLayer);
        scene.attachChild(logoLayer);
        scene.attachChild(popupLayer);

        this.init();

        return this.scene;
    }

    @Override
    public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
        return false;
    }

    private void init() {
        this.initBG();
        this.initHero();
        this.initClouds();
        this.initLandscape();
        this.initMainMenu();
        this.initAreaTouch();

        if (showErrorReport) {
            final String exception = mSQLiteHelper.queryAndLogExceptions();

            //toastOnUiThread(exception);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    AlertDialog.Builder alert = new AlertDialog.Builder(StartMenuScreen.this);
                    alert.setTitle("Error report");
                    alert.setMessage(exception);
                    alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    });
                    AlertDialog dialog = alert.show();
                    TextView textView = (TextView) dialog.findViewById(R.id.message);
                    textView.setTextSize(10);
                    StartMenuScreen.showErrorReport = false;
                }
            });
        }
    }

    private void initLandscape() {
        generateRandomLevel();

    }

    private void initClouds() {

        for (int i = 0; i < 3; i++) {
            startNewCloud(); //always 3 clouds active on the screen
        }
    }

    private void startNewCloud() {

        int minY = 500;
        int totalYRange = CAMERA_HEIGHT - 100;
        float startYMin = minY;
        float startYMax = startYMin + totalYRange / 3 - 30;
        float startY = startYMin + new Random().nextInt(((int) (startYMax - startYMin)));

        int startX;
        startX = CAMERA_WIDTH + new Random().nextInt(800);

        final Sprite cloud = new Sprite(startX, startY, cloudTextureRegion, getVertexBufferObjectManager());
        landscapeLayer.attachChild(cloud);
        int speed = 30 + new Random().nextInt(10);
        cloud.registerEntityModifier(new MoveXModifier(speed, startX, -150, new IEntityModifier.IEntityModifierListener() {
            @Override
            public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {
            }

            @Override
            public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
                getEngine().runOnUpdateThread(new Runnable() {
                    @Override
                    public void run() {
                        cloud.detachSelf();
                    }
                });
                startNewCloud();
            }
        }));
    }

    private void initHero() {
        heroMovingSprite = new HeroSprite(CAMERA_WIDTH / 2, GROUND_Y, heroMovingRegion, getVertexBufferObjectManager());
        heroMovingSprite.setAnchorCenter(0.5f, 0);
        heroMovingSprite.animate(40);
        heroLayer.attachChild(heroMovingSprite);
    }

    private void initAreaTouch() {
        setBgTouchAreas(true);
        boolean savedGameExists = GameProfile.getAllFinishedLevels(mSQLiteHelper).size() > 0;
        if (!savedGameExists) {
            buttonContinueGame.setEnabled(false);
        }
    }

    private void initBG() {
        final Sprite bg = new Sprite(0, 0, this.bgTextureRegion, getVertexBufferObjectManager());
        bg.setAnchorCenter(0, 0);
        this.bgLayer.attachChild(bg);
        final Sprite logo = new Sprite(0, 0, this.logoTextureRegion, getVertexBufferObjectManager());
        logo.setAnchorCenter(0, 0);

        this.logoLayer.attachChild(logo);
        Sprite frame = new Sprite(0, 0, bgFrameRegion, getVertexBufferObjectManager());
        frame.setAnchorCenter(0, 0);
        frameLayer.attachChild(frame);
    }

    private void initMainMenu() {
        this.buttonNewGame = new CustomButtonSprite(
                CAMERA_WIDTH / 2, 190, buttonNewGameRegion.getTextureRegion(0), buttonNewGameRegion.getTextureRegion(1), buttonNewGameRegion.getTextureRegion(1), getVertexBufferObjectManager(),
                new CustomButtonSprite.OnClickListener() {
                    @Override
                    public void onClick(CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                        if (GameProfile.getAllFinishedLevels(mSQLiteHelper).size() > 0) {
                            StartMenuScreen.this.initConfirmWindow();
                            windowConfirmNewGame.detachSelf();
                            popupLayer.attachChild(windowConfirmNewGame);
                            backButtonAction = closeConfirmAction;
                            revealEntityAndChildren(0.3f, 0, 1f, popupLayer, null);
                            scene.registerTouchArea(buttonYesNewGame);
                            scene.registerTouchArea(buttonNoNewGame);
                            setBgTouchAreas(false);
                        } else {
                            startNewGame("normal");
                        }
                    }
                }
        );
        this.logoLayer.attachChild(this.buttonNewGame);

        this.buttonContinueGame = new CustomButtonSprite(
                CAMERA_WIDTH / 2, 255, buttonContinueRegion.getTextureRegion(0), buttonContinueRegion.getTextureRegion(1),
                buttonContinueRegion.getTextureRegion(1),
                getVertexBufferObjectManager(),
                new CustomButtonSprite.OnClickListener() {
                    @Override
                    public void onClick(CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                        continueGame("normal");
                    }
                }
        );
        this.logoLayer.attachChild(this.buttonContinueGame);

        this.buttonSettings = new CustomButtonSprite(
                CAMERA_WIDTH / 2, 125, buttonSettingsRegion.getTextureRegion(0), buttonSettingsRegion.getTextureRegion(1), getVertexBufferObjectManager(),
                new CustomButtonSprite.OnClickListener() {
                    @Override
                    public void onClick(CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                        showSettingsPopup();
                    }
                }
        );
        this.logoLayer.attachChild(this.buttonSettings);

        Sprite loonyRocket = new Sprite(CAMERA_WIDTH / 2, 30, loonyRocketCopyright, getVertexBufferObjectManager());
        logoLayer.attachChild(loonyRocket);

        putSparklingStar(CAMERA_WIDTH / 2 + 150, CAMERA_HEIGHT - 60, bgLayer);
        putSparklingStar(CAMERA_WIDTH / 2 + 190, CAMERA_HEIGHT - 95, bgLayer);
        putSparklingStar(CAMERA_WIDTH / 2 + 95, CAMERA_HEIGHT - 85, bgLayer);
        putSparklingStar(CAMERA_WIDTH / 2 + 165, CAMERA_HEIGHT - 48, bgLayer);
        putSparklingStar(CAMERA_WIDTH / 2 - 140, CAMERA_HEIGHT - 50, bgLayer);
        putSparklingStar(CAMERA_WIDTH / 2 - 90, CAMERA_HEIGHT - 100, bgLayer);
        putSparklingStar(CAMERA_WIDTH / 2 - 170, CAMERA_HEIGHT - 65, bgLayer);
        putSparklingStar(CAMERA_WIDTH / 2 - 85, CAMERA_HEIGHT - 45, bgLayer);
    }

    private void setBgTouchAreas(boolean enabled) {
        LOG.i("toggle bg touch areas " + enabled, 1);
        if (enabled) {
            scene.registerTouchArea(buttonNewGame);
            scene.registerTouchArea(buttonSettings);
            scene.registerTouchArea(buttonContinueGame);
        } else {
            scene.unregisterTouchArea(buttonNewGame);
            scene.unregisterTouchArea(buttonSettings);
            scene.unregisterTouchArea(buttonContinueGame);
        }

    }

    private void putSparklingStar(float x, float y, Entity layer) {
        Sprite star = new Sprite(x, y, starRegion, getVertexBufferObjectManager());
        layer.attachChild(star);
        star.registerEntityModifier(new LoopEntityModifier(
                new SequenceEntityModifier(
                        new DelayModifier(0.1f * new Random().nextInt(10)),
                        new AlphaModifier(1f, 0.3f, 1f),
                        new AlphaModifier(1f, 1f, 0.3f)
                )
        ));
    }


    private void initConfirmWindow() {
        windowConfirmNewGame = new Entity();
        Sprite windowConfirmBg = new Sprite(0, 0, this.winTextTextureRegion, getVertexBufferObjectManager());
        windowConfirmBg.setAnchorCenter(0, 0);
        windowConfirmNewGame.attachChild(windowConfirmBg);
        closeConfirmAction = new Runnable() {
            @Override
            public void run() {
                windowConfirmNewGame.detachSelf();
                scene.unregisterTouchArea(buttonYesNewGame);
                scene.unregisterTouchArea(buttonNoNewGame);
                setBgTouchAreas(true);
                backButtonAction = null;
            }
        };

        buttonYesNewGame = new CustomButtonSprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 - 107, buttonYesTextureRegion.getTextureRegion(0),
                buttonYesTextureRegion.getTextureRegion(1), getVertexBufferObjectManager(),
                new CustomButtonSprite.OnClickListener() {
                    @Override
                    public void onClick(CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                        startNewGame("normal");
                    }
                });

        windowConfirmNewGame.attachChild(buttonYesNewGame);

        buttonNoNewGame = new CustomButtonSprite(CAMERA_WIDTH - 88, CAMERA_HEIGHT / 2 + 189, buttonCloseTextureRegion.getTextureRegion(0),
                buttonCloseTextureRegion.getTextureRegion(1), getVertexBufferObjectManager(),
                new CustomButtonSprite.OnClickListener() {
                    @Override
                    public void onClick(CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                        revealEntityAndChildren(0.3f, 1, 0, popupLayer, new Runnable() {
                            @Override
                            public void run() {
                                runOnUpdateThread(closeConfirmAction);
                            }
                        });
                    }
                });

        windowConfirmNewGame.attachChild(buttonNoNewGame);

    }

    private void continueGame(String normal) {
        //GameProfile.
        startGame(normal);
    }

    private void startGame(final String model) {
        GameProfile.initGameProfile(mSQLiteHelper);
        Intent intent = new Intent();
        intent.putExtra("mode", model);
        intent.setClass(this.getApplicationContext(), LevelMapScreen.class);
        startActivity(intent);
        StartMenuScreen.this.finish();
    }

    private void startNewGame(String normal) {
        GameProfile.eraseSavedGame(mSQLiteHelper);
        startGame(normal);
    }

    private LandscapeArea[] landscapeAreas = new LandscapeArea[]{l(TOWN, 4), l(BLOSSOM_HILLS, 5), l(GRAIN, 4), l(OAKS, 3, 0, 1, 2), l(CASTLE, 6), l(DARK_FOREST, 2), l(DARK_ROCKS, 4), l(DEAD_FOREST, 1), l(TOWN_BLUE, 3, 1), l(DARK_FOREST, 4), l(DEAD_FOREST_LAVA, 4), l(ROCK, 5), l(HILLS, 3)};//42


    private List<LandscapeItem> generateRandomLevel() {
        List<LandscapeItem> result = new LinkedList<LandscapeItem>();
        LandscapeType prevStyle = null;
        int curIndex = 0;

        for (int i = 0; i < landscapeAreas.length; i++) {
            int lsSequenceLength = landscapeAreas[i].getAreaLength();
            LandscapeType style = landscapeAreas[i].getType();
            int prevLsSteps = -1;
            LsTextureDef prevTextureDef = null;
            int lsIndex = 0;

            for (int j = 0; j < lsSequenceLength; ) {
                int remainSteps = lsSequenceLength - j;
                LsTextureDef textureDef = null;
                if (landscapeAreas[i].getLsIndices() != null && landscapeAreas[i].getLsIndices().length > 0) {
                    textureDef = getLandScapeForStyleByIndex(style, landscapeAreas[i].getLsIndices()[lsIndex++]);
                } else {
                    textureDef = getMaxLandScapeForStyle(style, remainSteps);
                }
                prevTextureDef = textureDef;
                for (int k = 0; k < textureDef.getSteps(); k++) {
                    LandscapeItem item = new LandscapeItem();
                    item.setLandscapeType(style);
                    result.add(item);
                    if (k == 0) {
                        float placeX = 0 + LANDSCAPE_ITEM_WIDTH * curIndex + (textureDef.getSteps() * LANDSCAPE_ITEM_WIDTH / 2);

                        LandscapeSprite sprite = new LandscapeSprite(placeX, GROUND_Y - 7f,
                                textureDef.getTextureRegion() != null ? textureDef.getTextureRegion() : textureDef.getBaseTextureRegion(), getVertexBufferObjectManager());
                        sprite.setAnchorCenter(0.5f, 0);
                        item.setLandscapeSprite(sprite);
                        landscapeLayer.attachChild(sprite);
                        moveLeft(sprite);
                    }
                    Sprite lsBaseSprite = new Sprite(LANDSCAPE_ITEM_WIDTH * (result.size() - 1) + LANDSCAPE_ITEM_WIDTH / 2, GROUND_Y - 7f,
                            textureDef.getBaseTextureRegion(), getVertexBufferObjectManager());
                    lsBaseSprite.setAnchorCenter(0.5f, 0);
                    item.setLsBasementSprite(lsBaseSprite);
                    landscapeBaseLayer.attachChild(lsBaseSprite);
                    moveLeft(lsBaseSprite);
                }
                j += textureDef.getSteps();
                curIndex += textureDef.getSteps();
                prevLsSteps = textureDef.getSteps();
            }
            NUMBER_ITEMS = curIndex;
        }
        return result;
    }

    public LsTextureDef getLandScapeForStyleByIndex(LandscapeType landscapeType, int lsIndex) {
        List<LsTextureDef> lsTextureDefs = landScapeTextureRegions.get(landscapeType);
        return lsTextureDefs.get(lsIndex);
    }

    public LsTextureDef getMaxLandScapeForStyle(LandscapeType landscapeType, int remainSteps) {
        List<LsTextureDef> lsTextureDefs = landScapeTextureRegions.get(landscapeType);
        Map<Integer, List<LsTextureDef>> texturesBySize = new HashMap<Integer, List<LsTextureDef>>();
        List<Integer> keyList = new LinkedList<Integer>();
        for (LsTextureDef ls : lsTextureDefs) {
            int steps = ls.getSteps();
            List<LsTextureDef> listForSteps = texturesBySize.get(steps);
            if (listForSteps == null) {
                listForSteps = new LinkedList<LsTextureDef>();
                texturesBySize.put(steps, listForSteps);
                keyList.add(steps);
            }
            listForSteps.add(ls);
        }
        //LOG.d("Retrieving maxLandscape for style " + landscapeType + ", remainSteps = " + remainSteps + ", stepKeys = " + keyList);
        int stepKeyIndex = keyList.size();
        List<LsTextureDef> listForSteps = null;
        do {
            stepKeyIndex--;
            listForSteps = texturesBySize.get(keyList.get(stepKeyIndex));
        } while (keyList.get(stepKeyIndex) > remainSteps);
        //LOG.d("Found max step length - " + keyList.get(stepKeyIndex));
        int select = MathUtils.random(0, listForSteps.size() - 1);
        return listForSteps.get(select);
    }


    private void moveLeft(final Sprite sprite) {
        sprite.registerEntityModifier(new MoveXModifier(0.5f, sprite.getX(), sprite.getX() - LANDSCAPE_ITEM_WIDTH, new IEntityModifier.IEntityModifierListener() {
            @Override
            public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {
                //To change body of implemented methods use File | Settings | File Templates.
            }

            @Override
            public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
                if (sprite.getX() < -100) {
                    sprite.setX(sprite.getX() + NUMBER_ITEMS * LANDSCAPE_ITEM_WIDTH);
                }
                moveLeft(sprite);
            }
        }));

    }

    private void showSettingsPopup() {
        isPopupShown = true;
        setBgTouchAreas(false);
        final Sprite popupBg = new Sprite(0, 0, settingsPopupBgTextureRegion, getVertexBufferObjectManager());
        popupBg.setAnchorCenter(0, 0);
        popupLayer.attachChild(popupBg);
        settingSoundState = GameProfile.getSettingsPlaySounds(mSQLiteHelper);
        final Sprite settingsMusicV = new Sprite(CAMERA_WIDTH / 2 - 57, CAMERA_HEIGHT / 2 + 52, checkBoxV, getVertexBufferObjectManager());
        final Sprite settingsSoundV = new Sprite(CAMERA_WIDTH / 2 - 57, CAMERA_HEIGHT / 2 - 15, checkBoxV, getVertexBufferObjectManager());

        final Sprite playSoundsCheckboxContainer = new Sprite(CAMERA_WIDTH / 2 - 57, CAMERA_HEIGHT / 2 - 15, checkBoxN, getVertexBufferObjectManager()) {
            @Override
            public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN) {
                    settingSoundState = !settingSoundState;

                    if (settingSoundState == false) {
                        settingsSoundV.detachSelf();
                    } else {
                        popupBg.attachChild(settingsSoundV);
                    }
                }
                return true;
            }
        };

        settingMusicState = GameProfile.getSettingsPlayMusic(mSQLiteHelper);
        final Sprite playMusicCheckboxContainer = new Sprite(CAMERA_WIDTH / 2 - 57, CAMERA_HEIGHT / 2 + 52, checkBoxN, getVertexBufferObjectManager()) {
            @Override
            public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN) {
                    settingMusicState = !settingMusicState; //set opposite state
                    if (settingMusicState == false) {
                        settingsMusicV.detachSelf();
                    } else {
                        popupBg.attachChild(settingsMusicV);
                    }
                }
                return true;
            }
        };
        final Runnable closeSettingsAction = new Runnable() {
            @Override
            public void run() {
                GameProfile.selectedLevelAreaIndex = null;
                GameProfile.selectedLevelIndex = null;
                scene.unregisterTouchArea(buttonOkSettings);
                scene.unregisterTouchArea(buttonCloseSettings);
                scene.unregisterTouchArea(playMusicCheckboxContainer);
                scene.unregisterTouchArea(playSoundsCheckboxContainer);
                popupBg.detachSelf();
                setBgTouchAreas(true);
                backButtonAction = null;
            }
        };
        backButtonAction = closeSettingsAction;

        buttonOkSettings = new CustomButtonSprite(
                CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 - 110, buttonOkTextureRegion.getTextureRegion(0), buttonOkTextureRegion.getTextureRegion(1), getVertexBufferObjectManager(),
                new CustomButtonSprite.OnClickListener() {
                    @Override
                    public void onClick(CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                        GameProfile.setSettingsPlayMusic(settingMusicState, mSQLiteHelper);
                        GameProfile.setSettingsPlaySound(settingSoundState, mSQLiteHelper);
                        revealEntityAndChildren(0.3f, 1, 0, popupLayer, closeSettingsAction);

                    }
                }
        );
        buttonCloseSettings = new CustomButtonSprite(
                CAMERA_WIDTH / 2 + 152, CAMERA_HEIGHT / 2 + 188, buttonCloseTextureRegion.getTextureRegion(0), buttonCloseTextureRegion.getTextureRegion(1), getVertexBufferObjectManager(),
                new CustomButtonSprite.OnClickListener() {
                    @Override
                    public void onClick(CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                        revealEntityAndChildren(0.3f, 1, 0, popupLayer, closeSettingsAction);

                    }
                }
        );

        popupBg.attachChild(buttonOkSettings);
        popupBg.attachChild(buttonCloseSettings);
        popupBg.attachChild(playMusicCheckboxContainer);
        popupBg.attachChild(playSoundsCheckboxContainer);
        if (GameProfile.getSettingsPlayMusic(mSQLiteHelper) == true) {
            popupBg.attachChild(settingsMusicV);
        } else {
            settingsMusicV.detachSelf();
        }
        if (GameProfile.getSettingsPlaySounds(mSQLiteHelper) == true) {
            popupBg.attachChild(settingsSoundV);
        } else {
            settingsSoundV.detachSelf();
        }


        revealEntityAndChildren(0.3f, 0, 1f, popupLayer, null);
        buttonOkSettings.setEnabled(true);
        scene.registerTouchArea(buttonOkSettings);
        scene.registerTouchArea(buttonCloseSettings);
        scene.registerTouchArea(playMusicCheckboxContainer);
        scene.registerTouchArea(playSoundsCheckboxContainer);
    }


    @Override
    public synchronized void onResume() {
        this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        super.onResume();    //To change body of overridden methods use File | Settings | File Templates.
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        LOG.i("keydown backbuttonaction = " + backButtonAction);
        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
            if (backButtonAction != null) {
                runOnUpdateThread(backButtonAction);
                LOG.i("keydown running action, now action = " + backButtonAction);
            } else {
                finish();
            }
            return true;
        } else {
            return super.onKeyDown(keyCode, event);    //To change body of overridden methods use File | Settings | File Templates.
        }
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();    //To change body of overridden methods use File | Settings | File Templates.
    }
}
